/**
 * Copyright (C) 2010 Cloudfarming <info@cloudfarming.nl>
 *
 * Licensed under the Eclipse Public License - v 1.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.eclipse.org/legal/epl-v10.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package nl.cloudfarming.client.sensor.cropcircle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import nl.cloudfarming.client.logging.AppLogFactory;
import nl.cloudfarming.client.logging.AppLogger;
import nl.cloudfarming.client.sensor.SensorProcessorProvider;
import nl.cloudfarming.client.util.FilePickerUtil;
import nl.cloudfarming.client.util.MD5Sum;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider;

/**
 * Processor for cropcircle data
 * 
 * @author Timon Veenstra
 */
@ServiceProvider(service = SensorProcessorProvider.class)
public class CropcircleProcessorProvider implements SensorProcessorProvider {

    private static final AppLogger LOG = AppLogFactory.getLogger(CropcircleProcessorProvider.class);
    private static final String LOGKEY_FILE_ALREADY_IMPORTED = "cropcircle.processorprovider.loginfo.file_alread_imported";
    private final String filefilterDescription = NbBundle.getMessage(this.getClass(), "cropcircle.processorprovider.filefilter.description", FilePickerUtil.getFileFilterTypeString(Arrays.asList(getSupportedExtentions())));


    @Override
    public String[] getSupportedExtentions() {
        return new String[]{".csv", ".txt"};
    }

    @Override
    public boolean isSupported(File sensorFile) {
        String fileExtension = sensorFile.getName().substring(sensorFile.getName().lastIndexOf("."));

        // 1: Check extension
        if(!Arrays.asList(getSupportedExtentions()).contains(fileExtension.toLowerCase())){
            return false;
        }

        // TODO: CHECK HEADER?
        // 2: Check fileheader
        
        // If preceeding code is passed this file is considered supported.
        return true;
    }

    // TODO: CHECK HEADER?
    @Override
    public boolean isValid(File sensorFile) {
        try {
            String checkSum = MD5Sum.getHex(MD5Sum.createChecksum(new FileInputStream(sensorFile)));
            String fileName = sensorFile.getName();
            if (new CropcircleServiceImpl().findFileByNameAndChecksum(fileName, checkSum) == null) {
                return true;
            } else {
                LOG.info(LOGKEY_FILE_ALREADY_IMPORTED, fileName);
            }
        } catch (NoSuchAlgorithmException ex) {
            LOG.error(ex.getMessage());
        } catch (IOException ex) {
            LOG.error(ex.getMessage());
        }
        
        
        
        return false;
    }

    @Override
    public String getFormatDescription() {
        return this.filefilterDescription;
    }

    /**
     * Retrieve first line of specified file and determine if this line is the right header for an Asc340 sensorfile
     * @param sensorFile The sensorfile to check header from
     * @return True if the header is indeed an asc340-header
     */
    private boolean hasAsc340Header(File sensorFile){
        String firstLine = "";
        try {
            BufferedReader br = new BufferedReader(new FileReader(sensorFile));
            firstLine = br.readLine();
            
            // firstLine should not be null
            firstLine = firstLine == null ? "" : firstLine;
        } catch (FileNotFoundException ex) {
            Exceptions.printStackTrace(ex);
        } catch (IOException ex) {
            Exceptions.printStackTrace(ex);
        }  
        
        boolean isCropcircleASC340= true;
        for(CropcircleASC340FileDescription value : CropcircleASC340FileDescription.values()){
            if(!firstLine.contains(value.toString())){
                isCropcircleASC340 = false;
                break;
            }    
        }
        return isCropcircleASC340;
    }
            
            
    @Override
    public CropcircleFileProcessor getProcessor(File sensorFile) {     
        // Determine which FileProcessor is needed for this cropcircle file
        if(hasAsc340Header(sensorFile)){
           return new CropcircleASC340FileProcessor(sensorFile);
        }
        
        String columnMissing = NbBundle.getMessage(this.getClass(), "cropcircle.processorprovider.logerror.column_missing", sensorFile.getName());
            
        LOG.warning(columnMissing);
        
        return null;
    }
}
